package org.darkforest.dao.redis.templete;

import org.darkforest.common.util.JacksonsUtil;

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by valentina on 15/2/18.
 */
public abstract class AbstractListRedisOper<T> extends AbstractBaseRedisDao<String,String>{

    private Class<T> cls = null;

    private Class<T> getObjClass(){
        if(cls==null){
            cls = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
        return cls;
    }

    /**
     * 将java类型列表转换为json格式redis列表存储
     * @param key
     * @param list
     * @return
     */
    public void addList(String key,List<T> list) {
        //先清空，再添加，防止重复加载数据
        deleteListByKey(key);
        for(T obj:list){
//            JSONObject jsonObject = JSONObject.fromObject(obj);
            String jsonStr = JacksonsUtil.newInstance().readAsString(obj);
            redisTemplate.boundListOps(key).rightPush(jsonStr);
        }
    }

    /**
     * 从redis中获取json格式列表，并将json转换为java列表
     * @param key
     * @return
     */
    public List getList(String key) {
        List<T> res = new ArrayList<T>();
        int listSize = getListSize(key);
        //循环从redis列表中取出对象并转换为java对象并加入list
        for(int i=0;i<listSize;i++){
            String jsonStr = redisTemplate.boundListOps(key).index(new Long(i));   //使用index顺序读取redis列表元素，转换为java对象并存入list
//            JSONObject jsonObject = JSONObject.fromObject(jsonStr);
//            T obj = (T)JSONObject.toBean(jsonObject,getObjClass());
            T obj = JacksonsUtil.newInstance().json2Obj(jsonStr,getObjClass());
            res.add(obj);
        }
        return res;
    }

    /**
     * 根据key值将整个list删除
     * @param key
     */
    public void deleteListByKey(String key) {
        int listSize = getListSize(key);
        if(listSize>0){
            for(int i=0;i<listSize;i++){
                redisTemplate.boundListOps(key).rightPop();
            }
        }
    }

    /**
     * 获取redis列表的长度
     * @param key
     * @return
     */
    public int getListSize(String key){
        Long size = redisTemplate.boundListOps(key).size();
        return size.intValue();
    }

    /**
     * 根据key，下标获取
     * @param key
     * @param index
     * @return
     */
    public T get(String key,int index){
        String jsonStr = redisTemplate.boundListOps(key).index(new Long(index));
//        JSONObject jsonObject = JSONObject.fromObject(jsonStr);
//        T res = (T)jsonObject.toBean(jsonObject,getObjClass());
        T res = JacksonsUtil.newInstance().json2Obj(jsonStr,getObjClass());
        return res;
    }

    /**
     * 向指定key的列表中加入对象
     * @param key
     * @param obj
     */
    public void add(String key,T obj){
//        JSONObject jsonObject = JSONObject.fromObject(obj);
        String jsonStr = JacksonsUtil.newInstance().readAsString(obj);
        redisTemplate.boundListOps(key).rightPush(jsonStr);
    }

    /**
     * 对指定key，指定位置的redis元素进行更新
     * @param key
     * @param index
     * @param obj
     */
    public void set(String key,int index,T obj){
        int listSize = this.getListSize(key);
        //防止下标越界
        if(index<listSize-1){
//            JSONObject jsonObject = JSONObject.fromObject(obj);
            String jsonStr = JacksonsUtil.newInstance().readAsString(obj);
            redisTemplate.boundListOps(key).set(new Long(index),jsonStr);
        }
    }

    /**
     * 对指定key，指定位置的redis列表元素进行删除
     * @param key
     * @param index
     */
    public void remove(String key,int index){
        int listSize = this.getListSize(key);
        //防止下标越界
        if(index<listSize-1){
            for (int i=0;i<listSize;i++){
                String jsonStr = redisTemplate.boundListOps(key).leftPop();
                if(i!=index){
                    redisTemplate.boundListOps(key).rightPush(jsonStr);
                }
            }
        }
    }

    /**
     * 对指定key的列表截取子列表
     * @param key
     * @param start
     * @param end
     */
    public void trim(String key,int start,int end){
        int listSize = this.getListSize(key);
        if(start>0 && start<end && start<listSize-1 && end<listSize-1){
            redisTemplate.boundListOps(key).trim(new Long(start),new Long(end));
        }
    }

}
